package thing

import (
	"github.com/gin-gonic/gin"
	ctrl_cali "github.com/wsw188440873/ctrl-cali"
	"github.com/wsw188440873/ctrl-cali/hub"
	types2 "github.com/wsw188440873/ctrl-cali/types"
	"iot-base/auth/api/logic"
	Log "iot-base/auth/logger"
	types3 "iot-base/auth/types"
	"strings"
)

type CaliStatus struct {
	ModelId string      `json:"model_id"`
	Type    string      `json:"type"`  // 空字符串 正常状态,  zero 零气校准, span  跨度校准
	Event   string      `json:"event"` // start 开始  cancel 取消， confirm 确认事件
	Params  interface{} `json:"-"`
}

var caliStatus CaliStatus

func Cali(c *gin.Context) {
	name := c.Param("type")
	switch name {
	case "zero":
		zero(c)
		return
	case "span":
		span(c)
		return
	default:
		resp := types3.NewResult(c)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
}

// span 跨度校准.
func span(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	uid := c.GetInt64("uid")
	resp := types3.NewResult(c)
	var req types3.ReqCalibratorSpan
	if err := c.ShouldBind(&req); err != nil {
		Log.Log.Errorf("[%s] [%v] err:=%v", requestId, uid, err)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	req.Units = strings.ToUpper(req.Units)
	stationLogic := logic.NewStationLogic()
	thingId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, req.ModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	//校准仪
	caliId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, types3.CaloModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	cali, err := ctrl_cali.NewCali("sailhero", req.StationId, thingId, caliId, req.ModelId, requestId.(string))
	if err != nil {
		resp.ErrorCode(types3.ParamsError, err.Error())
		return
	}
	err = cali.SpanCali(types2.SpanCali{
		Event:  req.Event,
		Number: req.Number,
		Units:  req.Units,
	})
	if err == nil {
		setStatic("span", req.Event, req.ModelId)
		caliStatus.Params = req
		resp.Success(gin.H{})
	} else {
		resp.ErrorCode(types3.Fail, err.Error())
	}
	return
}

// zero 零度校准.
func zero(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	uid := c.GetInt64("uid")
	resp := types3.NewResult(c)
	var req types3.ReqCalibratorZero
	if err := c.ShouldBind(&req); err != nil {
		Log.Log.Errorf("[%s] [%v] err:=%v", requestId, uid, err)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	stationLogic := logic.NewStationLogic()
	thingId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, req.ModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	//校准仪
	caliId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, types3.CaloModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	cali, err := ctrl_cali.NewCali("sailhero", req.StationId, thingId, caliId, req.ModelId, requestId.(string))
	if err != nil {
		resp.ErrorCode(types3.ParamsError, err.Error())
		return
	}

	err = cali.ZeroCali(types2.ZeroCali{
		Event: req.Event,
	})
	if err == nil {
		setStatic("zero", req.Event, req.ModelId)
		caliStatus.Params = req
		resp.Success(gin.H{})
	} else {
		resp.ErrorCode(types3.Fail, err.Error())
	}

}

func GetStatus(c *gin.Context) {
	resp := types3.NewResult(c)
	resp.Success(caliStatus)
}

func setStatic(caliType string, event string, modelId string) {
	switch caliType {
	case "span":
		caliStatus.Type = "span"
	case "zero":
		caliStatus.Type = "zero"
	}
	caliStatus.ModelId = modelId
	caliStatus.Event = event
}

func ClearStatus(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	resp := types3.NewResult(c)
	stationLogic := logic.NewStationLogic()
	switch caliStatus.Type {
	case "span":
		if caliStatus.Params != nil {
			if data, ok := caliStatus.Params.(types3.ReqCalibratorSpan); ok {
				thingId, _ := stationLogic.GetThingIdByStationIdAndModelId(data.StationId, caliStatus.ModelId)
				caliId, _ := stationLogic.GetThingIdByStationIdAndModelId(data.StationId, types3.CaloModelId)
				caliTask, _ := ctrl_cali.NewCali("sailhero", data.StationId, thingId, caliId, caliStatus.ModelId, requestId.(string))
				caliTask.SpanCali(types2.SpanCali{
					Event:  types3.End,
					Number: data.Number,
					Units:  data.Units,
				})
			}
		}
	case "zero":
		if caliStatus.Params != nil {
			if data, ok := caliStatus.Params.(types3.ReqCalibratorZero); ok {
				thingId, _ := stationLogic.GetThingIdByStationIdAndModelId(data.StationId, caliStatus.ModelId)
				caliId, _ := stationLogic.GetThingIdByStationIdAndModelId(data.StationId, types3.CaloModelId)
				caliTask, _ := ctrl_cali.NewCali("sailhero", data.StationId, thingId, caliId, caliStatus.ModelId, requestId.(string))
				caliTask.ZeroCali(types2.ZeroCali{
					Event: types3.End,
				})
			}
		}
	}

	caliStatus.Type = ""
	caliStatus.Event = ""
	caliStatus.ModelId = ""
	caliStatus.Params = nil
	resp.Success(gin.H{})
}

// CaliTask 校准任务.
func CaliTask(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	uid := c.GetInt64("uid")
	resp := types3.NewResult(c)
	var req types3.ReqCaliTask
	if err := c.ShouldBind(&req); err != nil {
		Log.Log.Errorf("[%s] [%v] err:=%v", requestId, uid, err)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	if !checkCliTaskType(req.TaskType) {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	stationLogic := logic.NewStationLogic()
	thingId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, req.ModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	//校准仪
	caliId, err := stationLogic.GetThingIdByStationIdAndModelId(req.StationId, types3.CaloModelId)
	if err != nil {
		resp.ErrorCode(types3.ParamsError, "")
		return
	}

	caliTask, err := ctrl_cali.NewCali("sailhero", req.StationId, thingId, caliId, req.ModelId, requestId.(string))
	if err != nil {
		resp.ErrorCode(types3.ParamsError, err.Error())
		return
	}
	//检查是否有任务正在执行.
	isRun := caliTask.IsRunTask()
	if isRun == true {
		Log.Log.Errorf("[%s] crontab.CaliTask.IsRun = %v", requestId, isRun)
		resp.ErrorCode(types3.Fail, "错误操作,其他任务正在运行.")
		return
	}

	// 运行校准任务
	taskId, err := caliTask.CaliTask("", req.TaskType, "自动测试", "manual", types2.GroupTask{})
	if err != nil {
		Log.Log.Errorf("[%s] [%v]  crontab.CaliTask.Run err=%v", requestId, uid, err)
		resp.ErrorCode(types3.Fail, err.Error())
		return
	}
	resp.Success(gin.H{"task_id": taskId})
	return
}

func StopCaliTask(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	uid := c.GetInt64("uid")
	resp := types3.NewResult(c)
	var req types3.ReqStopCaliTask
	if err := c.ShouldBind(&req); err != nil {
		Log.Log.Errorf("[%s] [%v] err:=%v", requestId, uid, err)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	hub.TaskManager.Stop()
	// 重新初始化參數.
	hub.TaskManager.RestParams()
	resp.Success(gin.H{})
	return
}

func QueryCaliTaskStatus(c *gin.Context) {
	requestId, _ := c.Get("RequestId")
	uid := c.GetInt64("uid")
	resp := types3.NewResult(c)
	var req types3.ReqQueryCaliTaskStatus
	if err := c.ShouldBind(&req); err != nil {
		Log.Log.Errorf("[%s] [%v] err:=%v", requestId, uid, err)
		resp.ErrorCode(types3.ParamsError, "")
		return
	}
	params := hub.TaskManager.GetTaskParams()
	var modelId string
	if value, ok := params["model_id"]; ok {
		modelId = value.(string)
	}
	var taskType string
	if value, ok := params["task_type"]; ok {
		taskType = value.(string)
	}
	var value string
	if v, ok := params["value"]; ok {
		value = v.(string)
	}
	var status int
	if v, ok := params["code"]; ok {
		status = v.(int)
	}
	var currTask int
	if v, ok := params["curr"]; ok {
		currTask = v.(int)
	}
	var totalTask int
	if v, ok := params["total"]; ok {
		totalTask = v.(int)
	}
	var taskId string
	if v, ok := params["task_id"]; ok {
		taskId = v.(string)
	}
	result := gin.H{
		"task_id":    taskId,
		"model_id":   modelId,
		"task_type":  taskType,
		"curr_task":  currTask,
		"total_task": totalTask,
		"value":      value,
		"status":     status,
	}
	resp.Success(result)
	return
}

func checkCliTaskType(taskType string) bool {
	for _, v := range types3.TaskCaliType {
		if taskType == v {
			return true
		}
	}
	return false
}
